using System.Dynamic;
using System.Web.Mvc;
using Ninject;
using Ninject.Parameters;
using NuGet.Enterprise.Server.Controllers.ActionResults;
using NuGet.Enterprise.Server.Infrastructure;
using NuGet.Enterprise.Server.Models;
using NuGet.Enterprise.Server.Configuration;
using System.Web;

namespace NuGet.Enterprise.Server.Controllers
{
    public class FeedController
        : Controller
    {
        private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger();

        private IServerPackageProvider _provider = null;
        private IServerPackageRepository _repository = null;

        private void InitializeStorage(string connectionName)
        {
            _provider = _provider ?? Application.Kernel.Get<IServerPackageProvider>(new ConstructorArgument("connectionName", connectionName));
            _repository = _repository ?? Application.Kernel.Get<IServerPackageRepository>(new ConstructorArgument("connectionName", connectionName));
        }

        [Inject]
        public IFeedProvider FeedProvider
        { get; set; }

        [Inject]
        public IFeedRepository FeedRepository
        { get; set; }

        public ActionResult Index(string connectionName)
        {
            this.InitializeStorage(connectionName);

            dynamic viewModel = new ExpandoObject();

            viewModel.CurrentFeed = FeedProvider.GetFeed(connectionName);
            viewModel.Feeds = FeedRepository.GetFeeds();
            viewModel.BaseUrl = HttpContext.Request.Url.GetComponents(System.UriComponents.SchemeAndServer,
                                                                      System.UriFormat.Unescaped);

            return View(viewModel);
        }

        public ActionResult Details(string connectionName, string id, string version)
        {
            this.InitializeStorage(connectionName);

            dynamic viewModel = new ExpandoObject();

            viewModel.CurrentFeed = FeedProvider.GetFeed(connectionName);

            var filename = id + "." + version + ".nupkg";
            var filepath = _provider.GetFullPath(filename);

            viewModel.CurrentPackage = _provider.GetPackage(filepath);

            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Search(string filter)
        {
            var url = HttpContext.Request.UrlReferrer.AbsolutePath;

            if (!string.IsNullOrEmpty(filter))
            {
                url += "?filter=" + System.Web.HttpUtility.UrlEncode(filter);
            }

            return Redirect(url);
        }

        public ActionResult Download(string connectionName, string id)
        {
            this.InitializeStorage(connectionName);

            using (NLog.NestedDiagnosticsContext.Push("ConnectionContext: {0}".FormatInvariant(connectionName)))
            {
                string fullpath = _provider.GetFullPath(id);

                Log.Info("Downloading file: {0}", fullpath);

                return new ConditionalGetResult
                    (
                        _provider.GetLastModified(fullpath),
                        delegate()
                        {
                            using (UserContext.Impersonate(BuildStoreSection.Current.Connections[connectionName].Credentials, UserContext.LogonType.LOGON32_LOGON_NEW_CREDENTIALS, UserContext.LogonProvider.LOGON32_PROVIDER_DEFAULT))
                            {
                                byte[] buffer = System.IO.File.ReadAllBytes(fullpath);

                                Log.Debug("{0} bytes buffered for download", buffer.LongLength);

                                return File(buffer, "application/zip", id);
                            }
                        }
                    );
            }
        }
    }
}
